package solution189;

/**
 * 189. Rotate Array
 * Rotate an array of n elements to the right by k steps.
 * For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
 */
public class Solution {
    // O(n) O(1)
    // This approach is based on the fact that when we rotate the array k times, k elements from the back end of the
    // array come to the front and the rest of the elements from the front shift backwards.
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        reverse(nums,0,nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }
    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }
    // O(n) O(1)
    // Store the number being replaced in a temptemp variable.
    // Then, place the replaced number(temp) at its correct position and so on, n times.
    public void rotate4(int[] nums, int k) {
        k = k % nums.length;
        int count = 0;// 终止条件，放入正确位置的个数
        for (int start = 0; count < nums.length; start++) {
            int current = start;
            int prev = nums[start];
            do {
                int next = (current + k) % nums.length;// 移动k后的位置，要放入的位置
                int temp = nums[next];
                nums[next] = prev;
                prev = temp;
                current = next;
                count++;
            } while (start != current);
        }
    }

    // O(n*k) O(1)
    public void rotate2(int[] nums, int k) {
        if (k <= 0) return;
        if (nums == null || nums.length <= 1) return;
        int n = nums.length;
        int temp, previous;
        for (int i = 0; i < k; i++) {
            previous = nums[n-1];
            for (int j = 0; j < n; j++) {
                temp = nums[j];
                nums[j] = previous;
                previous = temp;
            }
        }
    }

    // O(n) O(n)
    public void rotate3(int[] nums, int k) {
        if ( k <= 0) return;
        if (nums == null || nums.length <= 1) return;
        int n = nums.length;
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[(i+k)%n] = nums[i];
        }
//        for (int i = 0; i < n; i++) {
//            nums[i] = a[i];
//        }
        System.arraycopy(a,0, nums,0, n);
    }
}
